﻿using Bettzueche.Dampfross;
using Bettzueche.RLLibrary.Types;
using System;

namespace Bettzueche.DampfrossContinuum
{
    /// <summary>
    /// Wrapper für HexRichtung als <c>IActionID</c> und mit cast Operationen.
    /// </summary>
    public class Aktion : IActionID
    {
        static readonly HexRichtungen[] _spielzuge = (HexRichtungen[])Enum.GetValues(typeof(HexRichtungen));

        /// <summary>
        /// Gibt den Typ / die Richtung der Aktion (Enum <c>HexRichtungen</c>).
        /// </summary>
        /// <value>
        /// The type.
        /// </value>
        public HexRichtungen Typ { get; private set; }

        /// <summary>
        /// Gibt oder setzt die ID of this Type. Entspricht (int)aktion.Typ.
        /// </summary>
        /// <value>
        /// ID, die dem Typ entspricht. Seiteneffekt! Der Typ wird damit auch geändert.
        /// Falls id-Wert keinem Spielzug entspricht, wird bisheriger Typ beibehalten.
        /// </value>
        public int ID {
            get {
                return (int)Typ;
            }
            set {
                Typ = TryCast(value);
            }
        }

        private HexRichtungen TryCast(int i) {
            try {
                HexRichtungen z = Aktion._spielzuge[i];
                return z;
            }
            catch (Exception) {
                // Warnung ausgeben!!!
                return this.Typ;
            }
        }

        /// <summary>
        /// Returns a <see cref="System.String" /> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String" /> that represents this instance.
        /// </returns>
        public override string ToString() {
            return "Aktion: " + ID + "-" + Typ.ToString();
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode() {
            return Typ.GetHashCode();
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj) {
            Aktion other = obj as Aktion;
            if (other == null)
                return false;
            return Equals(other);
        }

        /// <summary>
        /// Determines whether the specified <see cref="Aktion" />, is equal to this instance.
        /// </summary>
        /// <param name="a">The <see cref="Aktion" /> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="Aktion" /> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public bool Equals(Aktion a) {
            if (a == null)
                return false;
            return this.Typ == a.Typ;
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="Aktion"/> to <see cref="HexRichtungen"/>.
        /// </summary>
        /// <param name="a">Aktion - not null</param>
        /// <returns>
        /// The result of the conversion.
        /// </returns>
        /// <exception cref="NullReferenceException">a is null</exception>
        public static implicit operator HexRichtungen(Aktion a) {
            return a.Typ;
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="Aktion"/> to the <see cref="System.Int32"/> a.ID.
        /// </summary>
        /// <param name="a">Aktion - not null</param>
        /// <returns>a.ID</returns>
        /// <exception cref="NullReferenceException">a is null</exception>
        public static implicit operator int(Aktion a) {
            return a.ID;
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="HexRichtungen"/> to <see cref="Aktion"/>.
        /// </summary>
        /// <param name="dir">The direction</param>
        /// <returns>
        /// The result of the conversion.
        /// </returns>
        public static implicit operator Aktion(HexRichtungen dir) {
            return new Aktion { Typ = dir };
        }

        /// <summary>
        /// Performs an explicit conversion from <see cref="System.Int32"/> to <see cref="Aktion"/>.
        /// </summary>
        /// <param name="i">The Aktion ID</param>
        /// <returns>
        /// The result of the conversion.
        /// </returns>
        /// <exception cref="System.InvalidCastException">
        /// Es gibt keine Spielzug-Entsprechung zur umzuwandelnden ID.
        /// Nur die Int32-Entsprechungen von <c>HexRichtungen</c> werden unterstützt!
        /// </exception>
        public static explicit operator Aktion(int i) {
            if (i < 0 || i >= Aktion._spielzuge.Length) {
                throw new InvalidCastException("Es gibt keine Spielzug-Entsprechung zur umzuwandelnden ID.");
            }
            return new Aktion { ID = i };
        }
    }
}
